namespace CLELCore.Assembly.CLELInstructions
{
	public static class ArgumentUtilities
	{
		public static bool IsArgument(CLELInstruction inst)
		{
			if(inst == null)
				return false;
			return IsArgument(inst.Opcode);
		}

		public static bool IsArgument(byte opcode)
		{
			if(IsLoadArgument(opcode) || IsStoreArgument(opcode))
				return true;
			return false;
		}

		public static bool IsLoadArgument(CLELInstruction inst)
		{
			if(inst == null)
				return false;
			return IsLoadArgument(inst.Opcode);
		}

		public static bool IsLoadArgument(byte opcode)
		{
			if(opcode == CLELOpcode.LDARG0 || opcode == CLELOpcode.LDARG1
				|| opcode == CLELOpcode.LDARG2 || opcode == CLELOpcode.LDARG3
				|| opcode == CLELOpcode.LDARGS || opcode == CLELOpcode.LDARGAS
				|| opcode == CLELOpcode.LDARG || opcode == CLELOpcode.LDARGA)
				return true;
			return false;
		}
		
		public static bool IsStoreArgument(CLELInstruction inst)
		{
			if(inst == null)
				return false;
			return IsStoreArgument(inst.Opcode);
		}
		
		public static bool IsStoreArgument(byte opcode)
		{
			if(opcode == CLELOpcode.STARGS || opcode == CLELOpcode.STARG)
				return true;
			return false;
		}
		
		
		public static bool GetLoadArgumentNumber(CLELInstruction inst,ref uint number)
		{
			if(inst == null)
				return false;
			byte opcode = inst.Opcode;
			if(opcode == CLELOpcode.LDARG0)
			{
				number = 0;
				return true;
			}
			else if(opcode == CLELOpcode.LDARG1)
			{
				number = 1;
				return true;
			}
			else if(opcode == CLELOpcode.LDARG2)
			{
				number = 2;
				return true;
			}
			else if(opcode == CLELOpcode.LDARG3)
			{
				number = 3;
				return true;
			}
			else if(opcode == CLELOpcode.LDARGS)
			{
				Ldargs ldargs = (Ldargs)inst;
				number = (uint)ldargs.Argument;
				return true;
			}
			else if(opcode == CLELOpcode.LDARGAS)
			{
				Ldargas ldargas = (Ldargas)inst;
				number = (uint)ldargas.Argument;
				return true;
			}
			else if(opcode == CLELOpcode.LDARG)
			{
				Ldarg ldarg = (Ldarg)inst;
				number = (uint)ldarg.Argument;
				return true;
			}
			else if(opcode == CLELOpcode.LDARGA)
			{
				Ldarga ldarga = (Ldarga)inst;
				number = (uint)ldarga.Argument;
				return true;
			}
			return false;
		}

		public static bool GetStoreArgumentNumber(CLELInstruction inst,ref uint number)
		{
			if(inst == null)
				return false;
			byte opcode = inst.Opcode;
			if(opcode == CLELOpcode.STARGS)
			{
				Stargs stargs = (Stargs)inst;
				number = (uint)stargs.Argument;
				return true;
			}
			else if(opcode == CLELOpcode.STARG)
			{
				Starg starg = (Starg)inst;
				number = (uint)starg.Argument;
				return true;
			}
			return false;
		}

		public static bool GetArgumentNumber(CLELInstruction inst,ref uint number)
		{
			return GetLoadArgumentNumber(inst,ref number) || GetStoreArgumentNumber(inst,ref number);
		}
	}
}
